// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

namespace SnapObjects.Expressions
{
    public class CacheCollection<TKey, TValue>
    {
        private readonly ICacheProvider _cache;
        private readonly IDictionary<TKey, TValue> _values;

        private readonly string _cacheSourceKind;
        private readonly Func<TKey, string> _cacheKeyGenerator;

        public CacheCollection(
            ICacheProvider cache,
            string cacheSourceKind,
            Func<TKey, string> cacheKeyGenerator)
        {
            _cache = cache;

            if (_cache == null)
            {
                _values = new ConcurrentDictionary<TKey, TValue>();
            }

            _cacheSourceKind = cacheSourceKind;
            _cacheKeyGenerator = cacheKeyGenerator;
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            var cacheKey = this.GetKey(key);

            return _cache != null
                ? _cache.TryGet(cacheKey, null, out value)
                : _values.TryGetValue(key, out value);
        }

        public void SetValue(TKey key, TValue value)
        {
            if (_cache != null)
            {
                var cacheKey = this.GetKey(key);

                _cache.Set(cacheKey, value, null);
            }
            else
            {
                _values[key] = value;
            }
        }

        public TValue GetOrSet(TKey key, Func<TValue> generateIfNotFind)
        {
            if (!this.TryGetValue(key, out var value))
            {
                value = generateIfNotFind();

                this.SetValue(key, value);
            }

            return value;
        }

        private string GetKey(TKey key)
        {
            return $"{_cacheSourceKind}_{_cacheKeyGenerator(key)}";
        }
    }
}
